﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Forms;
using System.Drawing;

namespace DotNet.Common
{
    #region 逻辑视图框控件
    /// <summary>
    /// 逻辑视图框控件
    /// </summary>
    public partial class LogicView : PictureBox
    {
        #region 变量
        LogicChanView m_logicChanView;

        /// <summary>
        /// 获取逻辑通道视图
        /// </summary>
        public LogicChanView ChanView
        {
            get
            {
                return m_logicChanView;
            }
        }
        #endregion

        #region 构造函数
        public LogicView()
        {
            InitializeComponent();
            InitializeCustom();
        }

        public LogicView(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
            InitializeCustom();
        }

        private void InitializeCustom()
        {
            m_logicChanView = new LogicChanView(this);

            this.BackColor = SystemColors.WindowFrame;
            this.Resize += new EventHandler(LogicView_Resize);
        }
        #endregion

        #region 默认事件响应
        void LogicView_Resize(object sender, EventArgs e)
        {
            m_logicChanView.Resize(10, 5, this.Height - 20, this.Width - 20);

            this.Refresh();
        }

        void LogicView_Paint(object sender, PaintEventArgs e)
        {

        }
        #endregion

        #region 公共函数
        public void Clear()
        {
            m_logicChanView.Value = null;
            m_logicChanView.AllChanList = null;
            m_logicChanView.ShowList = null;

            this.Refresh();
        }
        #endregion
    }
    #endregion

    #region 辅助结构
    /// <summary>
    /// X轴范围
    /// </summary>
    public struct Range
    {
        int m_min, m_max;

        /// <summary>
        /// X轴最小值
        /// </summary>
        public int Min
        {
            get { return m_min; }
            set { m_min = value; }
        }

        /// <summary>
        /// X轴最大值
        /// </summary>
        public int Max
        {
            get { return m_max; }
            set { m_max = value; }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="min">最小值</param>
        /// <param name="max">最大值</param>
        public Range(int min, int max)
        {
            m_min = min;
            m_max = max;
        }

        public static bool operator ==(Range left, Range right)
        {
            return left.Min == right.Min && left.Max == right.Max;
        }

        public static bool operator !=(Range left, Range right)
        {
            return !(left == right);
        }

        public override bool Equals(object o)
        {
            return base.Equals(o);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }

    /// <summary>
    /// 时间逻辑值结构
    /// </summary>
    public struct TimeLogicValue
    {
        /// <summary>
        /// 时间
        /// </summary>
        public int TimePoint;
        /// <summary>
        /// 逻辑电平值
        /// </summary>
        public int Value;
    }

    /// <summary>
    /// 线定义
    /// </summary>
    public struct WireInfo
    {
        /// <summary>
        /// 标识
        /// </summary>
        public string Identifier;
        /// <summary>
        /// 引脚数量
        /// </summary>
        public int Count;
    }

    /// <summary>
    /// 逻辑时间信息
    /// </summary>
    public struct LogicTimeInfo
    {
        /// <summary>
        /// 线（管脚）数量信息
        /// </summary>
        public int WireCount;
        /// <summary>
        /// 线（管脚）名称信息
        /// </summary>
        public string WireName;
        /// <summary>
        /// 时间序列
        /// </summary>
        public TimeLogicValue[] LogicValue;
    }

    /// <summary>
    /// 图形字符串
    /// </summary>
    internal struct GraphicString
    {
        /// <summary>
        /// 标识字符
        /// </summary>
        public string character;
        /// <summary>
        /// X轴放置位置
        /// </summary>
        public float position;
    }

    /// <summary>
    /// 滚动条类型
    /// </summary>
    public enum LogicScrollbars
    {
        /// <summary>
        /// 水平滚动条
        /// </summary>
        Horizontal,
        /// <summary>
        /// 垂直滚动条
        /// </summary>
        Vertical
    }
    #endregion

    #region 辅助类
    /// <summary>
    /// 逻辑通道视图，可包含多个通道
    /// </summary>
    public class LogicChanView
    {
        LogicScrollbar m_horBar, m_verBar;
        LogicViewCursor m_cursor;
        LogicChanData[] m_allChanValue;
        LogicChanData[] m_showChanArray;
        int m_top, m_left, m_height, m_width;
        int m_chanBlank = 5;
        int m_scrollHeight = 10;
        PictureBox m_fatherBox;
        Point m_captureDownLocation, m_captureUpLocation;
        Stack<Range> m_timeRangeStack;
        MouseButtons m_downButton = MouseButtons.None;
        Range m_moveTimeRange, m_currentTimeRange;
        MenuChanSelect m_menuChanSelect;
        string[] m_allChanList,m_showList;
        bool m_capture = false;
        bool m_chanCapture = false;
        bool m_computeBestFlag = true;

        /// <summary>
        /// 设置计算匹配，当有两个波形比较时，应设为false。
        /// </summary>
        public bool ComputeBestFlag
        {
            set { m_computeBestFlag = value; }
        }

        /// <summary>
        /// 获取或设置通道间空白像素大小
        /// </summary>
        public int ChanBlank
        {
            get { return m_chanBlank; }
            set { m_chanBlank = value; }
        }

        /// <summary>
        /// 时间单位
        /// </summary>
        public string TimeUnit
        {
            set
            {
                m_cursor.TimeUnit = value;
            }
        }

        public string[] AllChanList
        {
            set
            {
                m_allChanList = value;
            }
            get
            {
                return m_allChanList;
            }
        }

        public int MaxTimeLength
        {
            set
            {
                m_horBar.MaxValue = value;
            }
            get
            {
                return m_horBar.MaxValue;
            }
        }

        public string[] ShowList
        {
            set
            {
                if (value == null)
                {
                    m_showChanArray = null;
                    m_showList = null;
                }
                else
                {
                    Debug.Assert(m_allChanValue != null);

                    List<LogicChanData> oshowChanList = new List<LogicChanData>();
                    List<string> oValueList = new List<string>(value);
                    List<string> oShowList = new List<string>();
                    foreach (LogicChanData chanData in m_allChanValue)
                    {
                        if (oValueList.Remove(chanData.Label))
                        {
                            oshowChanList.Add(chanData);
                            oShowList.Add(chanData.Label);
                        }
                    }
                    m_showChanArray = oshowChanList.ToArray();
                    m_showList = oShowList.ToArray();

                    m_verBar.MaxValue = m_showChanArray.Length;
                    m_verBar.ScrollRange = new Range(0, m_verBar.MaxValue);

                    Resize();
                }
            }
            get
            {
                return m_showList;
            }
        }

        /// <summary>
        /// 设置时间逻辑数组
        /// </summary>
        public LogicTimeInfo[] Value
        {
            set
            {
                if (value == null)
                {
                    m_allChanValue = null;
                    m_cursor.XAxisValue = -1;
                    m_horBar.ScrollRange = new Range();
                }
                else
                {
                    Color[] lineColors = new Color[] { Color.YellowGreen, Color.Blue, Color.Red, Color.Yellow };
                    m_allChanValue = new LogicChanData[value.Length];
                    int index = 0;
                    foreach (LogicTimeInfo logicValue in value)
                    {
                        m_allChanValue[index] = new LogicChanData();
                        m_allChanValue[index].Value = logicValue.LogicValue;
                        m_allChanValue[index].BitCount = logicValue.WireCount;
                        m_allChanValue[index].Label = logicValue.WireName;
                        m_allChanValue[index].ForeColor = lineColors[index % 4];
                        index++;
                    }
                    m_timeRangeStack.Clear();

                    m_verBar.MaxValue = m_allChanValue.Length;
                    m_verBar.ScrollRange = new Range(0, m_verBar.MaxValue);
                }

                m_showChanArray = m_allChanValue;
            }
        }

        public LogicChanData[] AllChanData
        {
            get
            {
                return m_allChanValue;
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="fatherBox"></param>
        public LogicChanView(PictureBox fatherBox)
        {
            fatherBox.MouseDown += new MouseEventHandler(LogicChanView_MouseDown);
            fatherBox.MouseMove += new MouseEventHandler(LogicChanView_MouseMove);
            fatherBox.MouseUp += new MouseEventHandler(LogicChanView_MouseUp);
            fatherBox.Paint += new PaintEventHandler(LogicChanView_Paint);
            fatherBox.MouseDoubleClick += new MouseEventHandler(LogicChanView_MouseDoubleClick);

            m_fatherBox = fatherBox;
            m_timeRangeStack = new Stack<Range>();
            m_cursor = new LogicViewCursor();
            m_horBar = new LogicScrollbar(LogicScrollbars.Horizontal);
            m_verBar = new LogicScrollbar(LogicScrollbars.Vertical);
            m_menuChanSelect = new MenuChanSelect();
            m_menuChanSelect.OnUpdateShowChanList += new StringArrayInvoker(UpdateShowChanList);

            m_captureDownLocation = m_captureUpLocation = new Point(-1, -1);
        }

        public void MouseDown(MouseEventArgs e)
        {
            this.LogicChanView_MouseDown(null, e);
        }

        public void MouseMove(MouseEventArgs e)
        {
            this.LogicChanView_MouseMove(null, e);
        }

        public void MouseUp(MouseEventArgs e)
        {
            this.LogicChanView_MouseUp(null, e);
        }

        public void MouseDoubleClick(MouseEventArgs e)
        {
            this.LogicChanView_MouseDoubleClick(null, e);
        }

        public void UpdateShowChanList(string[] strArray)
        {
            this.ShowList = strArray;

            Paint();
        }

        /// <summary>
        /// 更新显示区域
        /// </summary>
        /// <param name="graphic">绘图对象</param>
        private void Paint(Graphics graphic)
        {
            if (m_capture && m_chanCapture && m_downButton == MouseButtons.Left)
            {
                if (m_captureDownLocation.X >= 0 && m_captureUpLocation.X >= 0)
                {
                    int x = (m_captureDownLocation.X <= m_captureUpLocation.X ? m_captureDownLocation.X : m_captureUpLocation.X);
                    int width = Math.Abs(m_captureUpLocation.X - m_captureDownLocation.X + 1);
                    graphic.FillRectangle(Brushes.Khaki, x, m_top, width, m_height - LogicViewCursor.CursorHeight - m_scrollHeight);
                }
            }

            if (m_showChanArray != null)
            {
                foreach (LogicChanData chan in m_showChanArray)
                {
                    chan.Paint(graphic);
                }
            }

            m_cursor.Paint(graphic);
            m_horBar.Paint(graphic);
            m_verBar.Paint(graphic);
        }

        /// <summary>
        /// 绘制视图
        /// </summary>
        private void Paint()
        {
            m_fatherBox.Refresh();
        }

        /// <summary>
        /// 绘图响应
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void LogicChanView_Paint(object sender, PaintEventArgs e)
        {
            Paint(e.Graphics);
        }

        /// <summary>
        /// 显示所有数据
        /// </summary>
        /// <param name="timeLength"></param>
        /// <returns></returns>
        public bool Show()
        {
            if (m_horBar.ScrollRange.Min == 0 && m_horBar.ScrollRange.Max == m_horBar.MaxValue)
            {
                return false;
            }

            return Update(true, new Range(0, m_horBar.MaxValue));
        }

        /// <summary>
        /// 放大
        /// </summary>
        /// <returns></returns>
        public bool ZoomIn()
        {
            if (m_horBar.ScrollRange.Max == m_horBar.ScrollRange.Min)
            {
                return false;
            }

            Range oRange = new Range();

            int horBarSize = m_horBar.ScrollRange.Max - m_horBar.ScrollRange.Min;
            int cursorOff = m_cursor.CurrentTimePoint - m_horBar.ScrollRange.Min;
            int oneFourthSize = horBarSize / 4;
            if (cursorOff < oneFourthSize)
            {
                oRange.Min = m_horBar.ScrollRange.Min;
                oRange.Max = m_horBar.ScrollRange.Min + horBarSize / 2;
            }
            else if (cursorOff > horBarSize / 4 * 3)
            {
                oRange.Min = m_horBar.ScrollRange.Max - horBarSize / 2;
                oRange.Max = m_horBar.ScrollRange.Max;
            }
            else
            {
                oRange.Min = m_cursor.CurrentTimePoint - oneFourthSize;
                oRange.Max = m_cursor.CurrentTimePoint + oneFourthSize;
            }

            return Update(true, oRange);
        }

        /// <summary>
        /// 缩小
        /// </summary>
        /// <returns></returns>
        public bool ZoomOut()
        {
            if (m_horBar.ScrollRange.Min == 0 && m_horBar.ScrollRange.Max == m_horBar.MaxValue)
            {
                return false;
            }

            Range oRange = new Range();

            int horBarSize = m_horBar.ScrollRange.Max - m_horBar.ScrollRange.Min;
            oRange.Min = m_cursor.CurrentTimePoint - horBarSize;
            oRange.Max = m_cursor.CurrentTimePoint + horBarSize;
            if (oRange.Min < 0)
            {
                oRange.Max -= oRange.Min;
                oRange.Min = 0;
            }
            if (oRange.Max > m_horBar.MaxValue)
            {
                oRange.Min -= (oRange.Max - m_horBar.MaxValue);
                oRange.Max = m_horBar.MaxValue;
                if (oRange.Min < 0)
                {
                    oRange.Min = 0;
                }
            }

            return Update(true, oRange);
        }

        /// <summary>
        /// 更新数据段
        /// </summary>
        /// <param name="addFlag">添加标记</param>
        /// <param name="time">时间范围</param>
        /// <returns></returns>
        private bool Update(bool addFlag, Range time)
        {
            if (time.Min >= time.Max || m_allChanValue == null)
            {
                Paint();
                return false;
            }

            if (addFlag)
            {
                m_timeRangeStack.Push(time);
                m_currentTimeRange = time;
            }

            if (m_showChanArray != null)
            {
                foreach (LogicChanData chan in m_showChanArray)
                {
                    chan.Update(time);
                }
            }

            m_horBar.ScrollRange = time;
            m_cursor.TimeRange = time;
            if (!(m_capture && m_downButton == MouseButtons.Right))
            {
                m_cursor.Update();
            }

            Paint();
            return true;
        }

        /// <summary>
        /// 缩放逻辑通道视图
        /// </summary>
        /// <param name="top">顶部</param>
        /// <param name="left">左部</param>
        /// <param name="height">高度</param>
        /// <param name="width">宽度</param>
        public void Resize(int top, int left, int height, int width)
        {
            if (top < 0 || left < 0 || height < LogicViewCursor.CursorHeight + m_scrollHeight || width < LogicChanData.LabelWidth)
                return;

            m_top = top;
            m_left = left;
            m_height = height;
            m_width = width;

            Resize();
        }

        /// <summary>
        /// 缩放通道
        /// </summary>
        private void Resize()
        {
            if (m_showChanArray == null || m_showChanArray.Length == 0)
                return;

            int totalChanHeight = m_height - LogicViewCursor.CursorHeight - m_scrollHeight;
            int chanBlankDouble = 2 * m_chanBlank;

            Range range = new Range(0, m_verBar.MaxValue);
            int chanHeight = totalChanHeight / m_verBar.MaxValue;
            if (chanHeight < m_chanBlank * 5)
            {
                chanHeight = m_chanBlank * 5;

                int chanCount = totalChanHeight / chanHeight;
                if (m_verBar.ScrollRange.Min + chanCount <= m_verBar.MaxValue)
                {
                    range = new Range(m_verBar.ScrollRange.Min, totalChanHeight / chanHeight + m_verBar.ScrollRange.Min);
                }
                else if (m_verBar.MaxValue - chanCount > 0)
                {
                    range = new Range(0, chanCount);
                }
            }
            Debug.Assert(chanHeight * (range.Max - range.Min) <= totalChanHeight);
            m_verBar.ScrollRange = range;

            int index = 0;
            foreach (LogicChanData chan in m_showChanArray)
            {
                if (index >= range.Min && index < range.Max)
                {
                    if (chan.Visible)
                    {
                        chan.Resize(m_top + chanHeight * (index - range.Min) + m_chanBlank, m_left, chanHeight - chanBlankDouble, m_width - m_scrollHeight);
                    }
                    else
                    {
                        chan.Visible = true;
                        chan.Update(m_currentTimeRange, m_top + chanHeight * (index - range.Min) + m_chanBlank, m_left, chanHeight - chanBlankDouble, m_width - m_scrollHeight);
                    }
                }
                else
                {
                    chan.Visible = false;
                }
                index++;
            }

            m_cursor.Resize(m_top, m_left + LogicChanData.LabelWidth, m_height - m_scrollHeight, m_width - LogicChanData.LabelWidth - m_scrollHeight);

            m_horBar.Resize(m_top + m_height - m_scrollHeight, m_left + LogicChanData.LabelWidth, m_scrollHeight, m_width - LogicChanData.LabelWidth - m_scrollHeight);
            m_verBar.Resize(m_top + m_chanBlank, m_left + m_width - m_scrollHeight, totalChanHeight - chanBlankDouble, m_scrollHeight);
        }

        /// <summary>
        /// 双击响应
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void LogicChanView_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && m_timeRangeStack.Count > 1)
            {
                m_timeRangeStack.Pop();
                m_currentTimeRange = m_timeRangeStack.Peek();
                Update(false, m_currentTimeRange);
            }
        }

        /// <summary>
        /// 鼠标按下响应
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void LogicChanView_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Clicks > 1)
                return;

            if (m_showChanArray == null || m_showChanArray.Length == 0)
            {
                m_capture = false;
                return;
            }

            if (e.Button == MouseButtons.Left || e.Button == MouseButtons.Right)
            {
                if (m_capture = (e.X >= m_left + LogicChanData.LabelWidth && e.X <= (m_left + m_width - m_scrollHeight)
                    && e.Y >= m_top && e.Y <= (m_top + m_height - m_scrollHeight)))
                {
                    if (e.Button == MouseButtons.Left)
                    {
                        m_chanCapture = (e.Y < m_top + m_height - m_scrollHeight - LogicViewCursor.CursorHeight);
                        m_cursor.XAxisValue = e.X;
                        m_cursor.CurrentTimePoint = ComputeBestTime(m_currentTimeRange.Min + CommonMath.OneVarEquation(e.X - m_left - LogicChanData.LabelWidth, m_currentTimeRange.Max - m_currentTimeRange.Min, m_width - LogicChanData.LabelWidth - m_scrollHeight));
                    }
                    else if (e.Button == MouseButtons.Right)
                    {
                        m_fatherBox.Cursor = System.Windows.Forms.Cursors.Hand;
                    }
                    m_captureDownLocation = e.Location;
                    m_downButton = e.Button;
                }
                else
                {
                    if (e.Button == MouseButtons.Right)
                    {
                        if (e.X >= 0 && e.X < m_left + LogicChanData.LabelWidth)
                        {
                            if (m_allChanList != null && m_allChanList.Length > 0)
                            {
                                m_menuChanSelect.Load(m_allChanList, m_showList);
                                m_menuChanSelect.Show(m_fatherBox, e.X, e.Y);
                            }
                        }
                    }
                }
            }
            else
            {
                m_capture = false;
            }
        }

        /// <summary>
        /// 鼠标移动响应
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void LogicChanView_MouseMove(object sender, MouseEventArgs e)
        {
            if (m_capture)
            {
                bool needPaintFlagUpDown = false, needPaintFlagLeftRight = false;

                // 垂直移动
                needPaintFlagUpDown = MoveChanUpDown(e.Button, e.Y);

                // 水平移动
                needPaintFlagLeftRight = MoveChanLeftRight(e.Button, e.X);

                if (needPaintFlagUpDown || needPaintFlagLeftRight)
                {
                    Paint();
                }
            }
        }

        private bool MoveChanUpDown(MouseButtons buttonType,int mouseY)
        {
            bool needPaintFlag = false;

            if (buttonType == MouseButtons.Right)
            {
                int YChanView = CommonMath.Nearest(mouseY, m_top, m_top + m_height - m_scrollHeight);
                if (m_captureDownLocation.Y != YChanView)
                {
                    int offChan = CommonMath.OneVarEquation(YChanView - m_captureDownLocation.Y, m_verBar.ScrollRange.Max - m_verBar.ScrollRange.Min, m_height - m_scrollHeight);

                    if (offChan != 0)
                    {
                        offChan = CommonMath.Nearest(offChan, m_verBar.ScrollRange.Max - m_verBar.MaxValue, m_verBar.ScrollRange.Min);
                        if (offChan != 0)
                        {
                            int minChan, maxChan;
                            minChan = m_verBar.ScrollRange.Min - offChan;
                            maxChan = m_verBar.ScrollRange.Max - offChan;

                            int i;
                            if (offChan > 0)
                            {
                                for (i = minChan; i < m_verBar.ScrollRange.Min; i++)
                                {
                                    m_showChanArray[i].Visible = true;
                                }
                                for (i = maxChan; i < m_verBar.ScrollRange.Max; i++)
                                {
                                    m_showChanArray[i].Visible = false;
                                }
                            }
                            else
                            {
                                for (i = m_verBar.ScrollRange.Min; i < minChan; i++)
                                {
                                    m_showChanArray[i].Visible = false;
                                }
                                for (i = m_verBar.ScrollRange.Max; i < maxChan; i++)
                                {
                                    m_showChanArray[i].Visible = true;
                                }
                            }

                            int totalChanHeight = m_height - LogicViewCursor.CursorHeight - m_scrollHeight;
                            int chanBlankDouble = 2 * m_chanBlank;
                            int chanHeight = totalChanHeight / (maxChan - minChan);
                            if (chanHeight < m_chanBlank * 5)
                            {
                                chanHeight = m_chanBlank * 5;
                            }
                            for (i = minChan; i < maxChan; i++)
                            {
                                m_showChanArray[i].Update(m_currentTimeRange, m_top + chanHeight * (i - minChan) + m_chanBlank, m_left, chanHeight - chanBlankDouble, m_width - m_scrollHeight);
                            }
                            m_captureDownLocation.Y = YChanView;
                            m_verBar.ScrollRange = new Range(minChan, maxChan);
                            needPaintFlag = true;
                        }
                    }
                }
            }

            return needPaintFlag;
        }

        private bool MoveChanLeftRight(MouseButtons buttonType,int mouseX)
        {
            bool needPaintFlag = false;

            int XChanView = CommonMath.Nearest(mouseX, m_left + LogicChanData.LabelWidth, m_left + m_width - m_scrollHeight);
            if (m_captureUpLocation.X != XChanView)
            {
                if (buttonType == MouseButtons.Left)
                {
                    m_cursor.XAxisValue = XChanView;
                    m_cursor.CurrentTimePoint = ComputeBestTime(m_currentTimeRange.Min + CommonMath.OneVarEquation(XChanView - m_left - LogicChanData.LabelWidth, m_currentTimeRange.Max - m_currentTimeRange.Min, m_width - LogicChanData.LabelWidth - m_scrollHeight));
                    needPaintFlag = true;
                }
                else if (buttonType == MouseButtons.Right)
                {
                    int offTime = CommonMath.OneVarEquation(XChanView - m_captureDownLocation.X, m_currentTimeRange.Max - m_currentTimeRange.Min, m_width - LogicChanData.LabelWidth - m_scrollHeight);
                    offTime = CommonMath.Nearest(offTime, m_currentTimeRange.Max - m_horBar.MaxValue, m_currentTimeRange.Min);
                    if (offTime != 0)
                    {
                        m_moveTimeRange.Min = m_currentTimeRange.Min - offTime;
                        m_moveTimeRange.Max = m_currentTimeRange.Max - offTime;
                        m_cursor.CurrentTimePoint = ComputeBestTime(m_moveTimeRange.Min + CommonMath.OneVarEquation(m_cursor.XAxisValue - m_left - LogicChanData.LabelWidth, m_moveTimeRange.Max - m_moveTimeRange.Min, m_width - LogicChanData.LabelWidth - m_scrollHeight));
                        Update(false, m_moveTimeRange);
                    }
                }

                m_captureUpLocation.X = XChanView;
            }

            return needPaintFlag;
        }

        /// <summary>
        /// 鼠标抬起响应
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void LogicChanView_MouseUp(object sender, MouseEventArgs e)
        {
            if (m_capture)
            {
                m_capture = false;
                if (m_captureDownLocation.X >= 0 && m_captureUpLocation.X < 0)
                {
                    m_cursor.XAxisValue = m_captureDownLocation.X;
                    Paint();
                }
                else if (m_captureDownLocation.X > 0 && m_captureUpLocation.X > 0 && m_captureDownLocation.X != m_captureUpLocation.X && m_timeRangeStack.Count > 0)
                {
                    bool updateFlag = false;

                    if (m_captureDownLocation.X == m_captureUpLocation.X)
                    {
                        Paint();
                    }
                    else
                    {
                        Range newRange = new Range();
                        if (m_downButton == MouseButtons.Left && m_chanCapture)
                        {
                            int downX = ComputeBestTime(m_currentTimeRange.Min + CommonMath.OneVarEquation(m_captureDownLocation.X - m_left - LogicChanData.LabelWidth, m_currentTimeRange.Max - m_currentTimeRange.Min, m_width - LogicChanData.LabelWidth - m_scrollHeight));
                            int upX = ComputeBestTime(m_currentTimeRange.Min + CommonMath.OneVarEquation(m_captureUpLocation.X - m_left - LogicChanData.LabelWidth, m_currentTimeRange.Max - m_currentTimeRange.Min, m_width - LogicChanData.LabelWidth - m_scrollHeight));

                            if (downX < upX)
                            {
                                newRange.Min = downX;
                                newRange.Max = upX;
                            }
                            else// if (downX > upX)
                            {
                                newRange.Min = upX;
                                newRange.Max = downX;
                            }

                            if (m_currentTimeRange != newRange)
                            {
                                updateFlag = true;
                            }
                        }
                        else if (e.Button == MouseButtons.Right)
                        {
                            if (m_currentTimeRange != m_moveTimeRange && m_moveTimeRange.Max != m_moveTimeRange.Min)
                            {
                                m_timeRangeStack.Pop();
                                newRange = m_moveTimeRange;
                                updateFlag = true;
                            }
                        }

                        if (updateFlag)
                        {
                            Update(true, newRange);
                        }
                        else
                        {
                            Paint();
                        }
                    }
                }
            }

            if (e.Button == MouseButtons.Right)
            {
                m_fatherBox.Cursor = System.Windows.Forms.Cursors.Arrow;
            }
            m_captureDownLocation.X = m_captureUpLocation.X = -1;
            m_moveTimeRange.Min = m_moveTimeRange.Max = 0;
            m_downButton = MouseButtons.None;
        }

        private int ComputeBestTime(int currentTime)
        {
            if (!m_computeBestFlag)
                return currentTime;

            int offTime = (m_currentTimeRange.Max - m_currentTimeRange.Min) / (m_width - LogicChanData.LabelWidth - m_scrollHeight);
            int minTime = currentTime - offTime;

            int timePoint;
            int bestTime = minTime;
            foreach (LogicChanData chan in m_showChanArray)
            {
                foreach (TimeLogicValue data in chan.Value)
                {
                    timePoint = data.TimePoint;
                    if (timePoint > bestTime && timePoint < currentTime)
                    {
                        if ((currentTime - timePoint) < offTime)
                        {
                            bestTime = timePoint;
                            offTime = currentTime - timePoint;
                        }
                    }
                }
            }

            if (bestTime == minTime)
            {
                bestTime = currentTime;
            }

            return bestTime;
        }
    }

    /// <summary>
    /// 逻辑通道数据类
    /// </summary>
    public class LogicChanData
    {
        Range m_time;
        int m_timeLength;
        int m_width = 0, m_height = 1, m_top, m_left, m_bottom, m_middle;
        Point[] m_lastPoint = new Point[2];
        int[] m_lastValue = new int[2];
        int[] m_lastTimePoint = new int[2];
        int m_lastIndex;
        TimeLogicValue[] m_value;
        List<Point> m_points = new List<Point>();
        List<GraphicString> m_strings = new List<GraphicString>();
        Pen m_linePen = new Pen(Color.Yellow);
        Brush m_stringBrush = new SolidBrush(Color.Yellow);
        const int m_fontSize = 9;
        const int m_fontHalfSize = 4;
        int m_bitCount;
        int m_valuePointX;
        string m_label;
        bool m_visible = true;
        bool m_showFlag = true;
        Range[] m_diffList;
        List<Rectangle> m_diffRectangle = new List<Rectangle>();
        Range m_lastRectangleRange = new Range();

        /// <summary>
        /// 标签宽度
        /// </summary>
        public const int LabelWidth = 70;

        /// <summary>
        /// 获取或设置时间逻辑数组
        /// </summary>
        public TimeLogicValue[] Value
        {
            get { return m_value; }
            set { m_value = value; Clear(); }
        }

        /// <summary>
        /// 值位数
        /// </summary>
        public int BitCount
        {
            get { return m_bitCount; }
            set { m_bitCount = value; }
        }

        /// <summary>
        /// 标签名称
        /// </summary>
        public string Label
        {
            get { return m_label; }
            set { m_label = value; }
        }

        /// <summary>
        /// 前景色
        /// </summary>
        public Color ForeColor
        {
            set
            {
                m_linePen.Color = value;
                m_stringBrush = new SolidBrush(value);
            }
        }

        public bool Visible
        {
            get { return m_visible; }
            set { m_visible = value; }
        }

        public bool ShowFlag
        {
            get { return m_showFlag; }
            set { m_showFlag = value; }
        }

        public Range[] DiffList
        {
            get { return m_diffList; }
            set
            {
                m_diffList = value;
                m_diffRectangle.Clear();
                if (m_width != 0)
                {
                    UpdateDiffView();
                }
            }
        }

        public LogicChanData()
        {
            m_time.Min = 0;
            m_time.Max = 1;
        }

        /// <summary>
        /// 缩放单通道视图
        /// </summary>
        /// <param name="top">顶部</param>
        /// <param name="left">左部</param>
        /// <param name="height">高度</param>
        /// <param name="width">宽度</param>
        public void Resize(int top, int left, int height, int width)
        {
            if (top < 0 || left < 0 || height < 0 || width < LogicChanData.LabelWidth)
                return;

            m_top = top;
            m_left = left;
            m_height = height;
            m_width = width;

            m_bottom = m_top + m_height;
            m_middle = (m_top + m_bottom) >> 1;

            Update();
        }

        /// <summary>
        /// 更新点数组
        /// </summary>
        public void Update()
        {
            Update(m_time);
        }

        /// <summary>
        /// 清除点数组
        /// </summary>
        private void Clear()
        {
            m_points.Clear();
            m_strings.Clear();
            m_diffRectangle.Clear();
            m_lastValue.Initialize();
            m_lastTimePoint[0] = m_lastTimePoint[1] = -1;
            m_lastPoint[0] = m_lastPoint[1] = Point.Empty;
            m_lastIndex = 0;
            m_valuePointX = 0;
            m_lastRectangleRange.Min = m_lastRectangleRange.Max = -1;
            m_visible = true;
        }

        /// <summary>
        /// 绘制时间逻辑曲线
        /// </summary>
        /// <param name="graphic"></param>
        public void Paint(Graphics graphic)
        {
            if (!m_visible)
                return;

            if (m_diffRectangle.Count > 0)
            {
                graphic.FillRectangles(Brushes.LightSalmon, m_diffRectangle.ToArray());
            }

            if (m_points.Count > 1)
            {
                graphic.DrawLines(m_linePen, m_points.ToArray());
            }

            if (m_height >= 14)
            {
                Font oFont = new Font("Arial", m_fontSize);
                int y = m_top + m_height / 2 - 7;

                if (!string.IsNullOrEmpty(m_label))
                {
                    graphic.DrawString(m_label, oFont, m_stringBrush, m_left, y);
                }
                foreach (GraphicString gs in m_strings)
                {
                    graphic.DrawString(gs.character, oFont, m_stringBrush, gs.position, y);
                }
            }
        }

        public void Update(Range time, int top, int left, int height, int width)
        {
            if (!m_visible)
                return;

            m_time = time;

            Resize(top, left, height, width);
        }

        /// <summary>
        /// 根据时间范围，更新点数组
        /// </summary>
        /// <param name="range">时间范围</param>
        public void Update(Range time)
        {
            if (!m_visible)
                return;

            Debug.Assert(time.Min < time.Max);
            m_time = time;
            m_timeLength = time.Max - time.Min;

            Clear();

            if (m_value == null || m_value.Length == 0)
                return;

            UpdateDiffView();

            if (m_bitCount == 1)
            {
                UpdateLineView();
            }
            else
            {
                UpdateValueView();
            }
        }

        /// <summary>
        /// 更新对比结果视图
        /// </summary>
        private void UpdateDiffView()
        {
            if (m_diffList == null || m_diffList.Length == 0)
                return;

            int length = m_diffList.Length;
            bool firstFlag = false;

            Range diffRange;
            for (int i = 0; i < length; i++)
            {
                diffRange = m_diffList[i];
                if (diffRange.Min >= m_time.Max)
                    break;

                if (firstFlag)
                {
                    if (diffRange.Max <= m_time.Max)
                    {
                        AddDiffRect(diffRange);
                    }
                    else
                    {
                        diffRange.Max = m_time.Max;
                        AddDiffRect(diffRange);
                    }
                }
                else
                {
                    if (diffRange.Max >= m_time.Min)
                    {
                        diffRange.Min = Math.Max(diffRange.Min, m_time.Min);
                        diffRange.Max = Math.Min(diffRange.Max, m_time.Max);
                        AddDiffRect(diffRange);
                        firstFlag = true;
                    }
                }
            }
        }

        private void AddDiffRect(Range diffRange)
        {
            Rectangle oRect = new Rectangle();
            oRect.X = m_left + LogicChanData.LabelWidth + CommonMath.OneVarEquation(diffRange.Min - m_time.Min, m_width - LogicChanData.LabelWidth, m_timeLength);
            oRect.Width = m_left + LogicChanData.LabelWidth + CommonMath.OneVarEquation(diffRange.Max - m_time.Min, m_width - LogicChanData.LabelWidth, m_timeLength) - oRect.Left + 1;
            Debug.Assert(oRect.Left <= oRect.Right);

            if (oRect.Right <= m_lastRectangleRange.Max)
            {
                return;
            }

            if (oRect.Left <= m_lastRectangleRange.Max)
            {
                int lastIndex = m_diffRectangle.Count - 1;
                if (lastIndex >= 0)
                {
                    int lastX = m_diffRectangle[lastIndex].X;
                    oRect.Width = oRect.Right - lastX;
                    oRect.X = lastX;
                    m_diffRectangle.RemoveAt(lastIndex);
                }
            }

            oRect.Y = m_top - 2;
            oRect.Height = m_bottom - m_top + 5;
            m_diffRectangle.Add(oRect);
            m_lastRectangleRange.Min = oRect.Left;
            m_lastRectangleRange.Max = oRect.Right;
        }

        /// <summary>
        /// 更新线类型视图
        /// </summary>
        private void UpdateLineView()
        {
            int length = m_value.Length;
            int timepoint = 0;
            bool firstFlag = false;
            int lastValue = 0;
            int newValue;

            for (int i = 0; i < length; i++)
            {
                timepoint = m_value[i].TimePoint;

                if (firstFlag) //添加时间逻辑值
                {
                    if (timepoint > m_time.Max)
                    {
                        break;
                    }

                    newValue = m_value[i].Value;
                    if (newValue != lastValue)
                    {
                        AddLinePoint(timepoint, lastValue);
                        lastValue = newValue;
                        AddLinePoint(timepoint, lastValue);
                    }
                }
                else // 查找第一个匹配时间逻辑值
                {
                    if (timepoint >= m_time.Min)
                    {
                        if (timepoint == m_time.Min)
                        {
                            lastValue = m_value[i].Value;
                        }
                        else
                        {
                            // 添加匹配前时间逻辑值
                            if (i == 0)
                            {
                                lastValue = 0;
                            }
                            else
                            {
                                lastValue = m_value[i - 1].Value;
                            }

                            AddLinePoint(m_time.Min, lastValue);
                            if (lastValue != m_value[i].Value)
                            {
                                AddLinePoint(timepoint, lastValue);
                                lastValue = m_value[i].Value;
                            }
                        }
                        firstFlag = true;

                        AddLinePoint(timepoint, lastValue);
                    }
                }
            }

            if (!firstFlag)
            {
                lastValue = m_value[length - 1].Value;

                AddLinePoint(m_time.Min, lastValue);
            }

            if ((timepoint != m_time.Max) || (m_points.Count == 1))
            {
                AddLinePoint(m_time.Max, /*lastValue*/m_lastValue[m_lastIndex]); //! Why
            }
        }

        /// <summary>
        /// 更新值类型视图
        /// </summary>
        private void UpdateValueView()
        {
            int length = m_value.Length;
            int timepoint = 0;
            bool firstFlag = false;
            int lastValue = 0;

            for (int i = 0; i < length; i++)
            {
                if (timepoint == m_time.Max)
                {
                    break;
                }
                timepoint = m_value[i].TimePoint;

                if (firstFlag) //添加时间逻辑值
                {
                    if (timepoint > m_time.Max)
                    {
                        break;
                    }

                    AddValuePoint(timepoint, lastValue);
                    lastValue = m_value[i].Value;
                }
                else // 查找第一个匹配时间逻辑值
                {
                    if (timepoint >= m_time.Min)
                    {
                        firstFlag = true;
                        AddValuePoint(m_time.Min, -1);
                        if (timepoint == m_time.Min)
                        {
                            lastValue = m_value[i].Value;
                        }
                        else
                        {
                            // 添加匹配前时间逻辑值
                            if (i == 0)
                            {
                                lastValue = 0;
                            }
                            else
                            {
                                lastValue = m_value[i - 1].Value;
                            }

                            if (timepoint > m_time.Max)
                            {
                                break;
                            }
                            AddValuePoint(timepoint, lastValue);
                            lastValue = m_value[i].Value;
                        }
                    }
                }
            }

            if (!firstFlag)
            {
                AddValuePoint(m_time.Min, -1);
                lastValue = m_value[length - 1].Value;
            }

            if ((timepoint != m_time.Max) || (m_points.Count == 1))
            {
                AddValuePoint(m_time.Max, lastValue);
            }

            // 补充重复眼图下半部分
            length = m_points.Count;
            Debug.Assert(length >= 4);
            List<Point> copyPoints = m_points.GetRange(0, length - 1);
            copyPoints.Reverse();
            for (int index = 0; index < length - 1; index++)
            {
                if (copyPoints[index].Y == m_top)
                {
                    copyPoints[index] = new Point(copyPoints[index].X, m_bottom);
                }
            }
            m_points.AddRange(copyPoints);
        }

        /// <summary>
        /// 添加点数组
        /// </summary>
        /// <param name="timePoint">时间</param>
        /// <param name="value">逻辑电平</param>
        /// <returns></returns>
        private bool AddLinePoint(int timePoint, int value)
        {
            if (timePoint < m_time.Min || timePoint > m_time.Max)
                return false;

            int nextIndex = (m_lastIndex + 1) % 2;
            if (timePoint < m_lastTimePoint[m_lastIndex])
            {
                return false;
            }
            else if (timePoint == m_lastTimePoint[m_lastIndex])
            {
                if (value == m_lastValue[m_lastIndex])
                {
                    return false;
                }
                else
                {
                    if (timePoint == m_lastTimePoint[nextIndex] && value == m_lastValue[nextIndex])
                    {
                        return false;
                    }
                }
            }

            Point p = new Point();
            p.X = m_left + LogicChanData.LabelWidth + CommonMath.OneVarEquation(timePoint - m_time.Min, m_width - LogicChanData.LabelWidth, m_timeLength);
            p.Y = (value != 0 ? m_top : m_bottom);
            if (m_points.Count > 0)
            {
                if (p == m_lastPoint[m_lastIndex])
                {
                    m_lastValue[m_lastIndex] = value;
                    return false;
                }
                else
                {
                    // 不添加重复画线的点
                    if (p == m_lastPoint[nextIndex])
                    {
                        //m_lastIndex = nextIndex;
                        m_lastValue[m_lastIndex] = value;
                        m_lastPoint[nextIndex] = m_lastPoint[m_lastIndex];
                        m_lastPoint[m_lastIndex] = p;
                        return false;
                    }
                    else if (m_points[m_points.Count - 1] != m_lastPoint[m_lastIndex])
                    {
                        m_points.Add(m_lastPoint[m_lastIndex]);
                    }
                }
            }
            m_points.Add(p);

            if (value == m_lastValue[m_lastIndex] && m_points.Count >= 2)
            {
                if ((p.X - m_lastPoint[m_lastIndex].X) >= 7)
                {
                    GraphicString gs;
                    gs.character = value.ToString();
                    gs.position = (p.X + m_lastPoint[m_lastIndex].X) / 2 - m_fontHalfSize;

                    m_strings.Add(gs);
                }
            }

            m_lastPoint[nextIndex] = p;
            m_lastTimePoint[nextIndex] = timePoint;
            m_lastValue[nextIndex] = value;
            m_lastIndex = nextIndex;

            return true;
        }

        /// <summary>
        /// 添加值类型点数组
        /// </summary>
        /// <param name="timePoint"></param>
        /// <param name="lastValue"></param>
        /// <returns></returns>
        private bool AddValuePoint(int timePoint, int lastValue)
        {
            if (timePoint < m_time.Min || timePoint > m_time.Max)
                return false;

            int x;
            Point p = new Point();
            if (timePoint == m_time.Min)
            {
                x = m_left + LogicChanData.LabelWidth;
                p.X = x;
                p.Y = m_middle;
                m_points.Add(p);
            }
            else
            {
                x = m_left + LogicChanData.LabelWidth + CommonMath.OneVarEquation(timePoint - m_time.Min, m_width - LogicChanData.LabelWidth, m_timeLength);
                int length = x - m_valuePointX;
                if (length < 1)
                {
                    return false;
                }
                else if (length == 1 || length == 2)
                {
                    p.X = m_valuePointX;
                    p.Y = m_top;
                    m_points.Add(p);
                    p.X = x;
                    m_points.Add(p);
                    p.Y = m_middle;
                    m_points.Add(p);
                }
                else
                {
                    p.X = m_valuePointX + 1;
                    p.Y = m_top;
                    m_points.Add(p);
                    p.X = x - 1;
                    m_points.Add(p);
                    p.X = x;
                    p.Y = m_middle;
                    m_points.Add(p);

                    int hexBits = CommonMath.DividCeiling(m_bitCount, 4);
                    string hexFormat = string.Format("X{0}", hexBits);
                    if (length >= 5 * hexBits + 2)
                    {
                        GraphicString gs;
                        gs.character = lastValue.ToString(hexFormat);
                        gs.position = (x + m_valuePointX) / 2 - m_fontHalfSize * hexBits;
                        m_strings.Add(gs);
                    }
                }
            }

            m_valuePointX = x;
            return true;
        }
    }

    /// <summary>
    /// 时间逻辑视图光标
    /// </summary>
    public class LogicViewCursor
    {
        Range m_timeRange;
        int m_xAxisValue = -1;
        int m_currectTimePoint;
        int m_top, m_left, m_height, m_width;
        string m_timeUnit;
        Pen m_linePen = new Pen(Color.PaleVioletRed, 2);

        /// <summary>
        /// 坐标高度
        /// </summary>
        public const int CursorHeight = 24;

        /// <summary>
        /// 时间坐标
        /// </summary>
        public int XAxisValue
        {
            get { return m_xAxisValue; }
            set { m_xAxisValue = value; }
        }

        public int CurrentTimePoint
        {
            get { return m_currectTimePoint; }
            set { m_currectTimePoint = value; }
        }

        /// <summary>
        /// 时间范围
        /// </summary>
        public Range TimeRange
        {
            get { return m_timeRange; }
            set { m_timeRange = value; }
        }

        /// <summary>
        /// X单位
        /// </summary>
        public string TimeUnit
        {
            set { m_timeUnit = value; }
        }

        /// <summary>
        /// 缩放
        /// </summary>
        /// <param name="top"></param>
        /// <param name="left"></param>
        /// <param name="height"></param>
        /// <param name="width"></param>
        public void Resize(int top, int left, int height, int width)
        {
            if (top < 0 || left < 0 || height < 0 || width < 0)
                return;

            m_top = top;
            m_left = left;
            m_height = height;
            m_width = width;

            Update();
        }

        /// <summary>
        /// 显示
        /// </summary>
        /// <param name="graphic"></param>
        public void Paint(Graphics graphic)
        {
            if (m_xAxisValue >= 0)
            {
                graphic.DrawLine(this.m_linePen, m_xAxisValue, m_top, m_xAxisValue, m_top + m_height - LogicViewCursor.CursorHeight);

                string timelabel;

                timelabel = string.Format("{0:N0} {1}", m_timeRange.Min, m_timeUnit);
                graphic.DrawString(timelabel, SystemFonts.CaptionFont, SystemBrushes.ActiveCaptionText, m_left, m_top + m_height - 14);

                timelabel = string.Format("{0:N0} {1}", m_timeRange.Max, m_timeUnit);
                graphic.DrawString(timelabel, SystemFonts.CaptionFont, SystemBrushes.ActiveCaptionText, m_left + m_width - timelabel.Length * 8, m_top + m_height - 14);

                timelabel = string.Format("{0:N0} {1}", m_currectTimePoint, m_timeUnit);
                int labelwidth = timelabel.Length * 8 + 2;
                int x = m_xAxisValue - (labelwidth >> 1);
                if (x < m_left)
                {
                    x = m_left;
                }
                else if (x + labelwidth > m_left + m_width)
                {
                    x = m_left + m_width - labelwidth;
                }
                int y = m_top + m_height - LogicViewCursor.CursorHeight;
                graphic.DrawString(timelabel, SystemFonts.CaptionFont, SystemBrushes.ActiveCaptionText, x, y);
                graphic.DrawRectangle(this.m_linePen, x, y, labelwidth, 13);
            }
        }

        /// <summary>
        /// 更新X值
        /// </summary>
        public void Update()
        {
            if (m_timeRange.Min < m_timeRange.Max && m_currectTimePoint >= m_timeRange.Min && m_currectTimePoint <= m_timeRange.Max)
            {
                m_xAxisValue = m_left + CommonMath.OneVarEquation(m_currectTimePoint - m_timeRange.Min, m_width, m_timeRange.Max - m_timeRange.Min);
            }
        }
    }

    /// <summary>
    /// 滚动条
    /// </summary>
    public class LogicScrollbar
    {
        int m_top, m_left, m_height, m_width;
        Range m_range;
        Pen m_linePen = new Pen(SystemColors.GrayText);
        int m_maxValue;
        const int m_minValue = 0;
        int m_barStart = -1, m_barWidth;
        LogicScrollbars m_scrollType = LogicScrollbars.Horizontal;

        /// <summary>
        /// 获取和设置范围
        /// </summary>
        public Range ScrollRange
        {
            get
            {
                return m_range;
            }
            set
            {
                m_range = value;

                InitBarSize();
            }
        }

        private void InitBarSize()
        {
            int valueLength = m_maxValue - m_minValue;
            if (valueLength <= 0)
                return;

            int controlStart, controlLength;
            switch (m_scrollType)
            {
                case LogicScrollbars.Horizontal:
                default:
                    controlStart = m_left;
                    controlLength = m_width;
                    break;
                case LogicScrollbars.Vertical:
                    controlStart = m_top;
                    controlLength = m_height;
                    break;
            }

            m_barStart = CommonMath.OneVarEquation(m_range.Min - m_minValue, controlLength, valueLength);
            m_barWidth = CommonMath.OneVarEquation(m_range.Max - m_range.Min, controlLength, valueLength);
            if (m_barWidth < 4)
            {
                if (controlLength < 4)
                {
                    m_barStart = 0;
                    m_barWidth = controlLength;
                }
                else
                {
                    m_barWidth = 4;
                    if (controlLength - m_barStart < 4)
                    {
                        m_barStart = controlLength - 4;
                    }
                }
            }
            m_barStart += controlStart;
        }

        /// <summary>
        /// 最小时间刻度范围
        /// </summary>
        private int MinValue
        {
            get
            {
                return 0;
            }
        }

        /// <summary>
        /// 最大时间刻度范围
        /// </summary>
        public int MaxValue
        {
            get
            {
                return m_maxValue;
            }
            set
            {
                m_maxValue = value;
            }
        }

        /// <summary>
        /// 滚动条类型
        /// </summary>
        public LogicScrollbars ScrollType
        {
            get
            {
                return m_scrollType;
            }
            set
            {
                m_scrollType = value;
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="scrollType"></param>
        public LogicScrollbar(LogicScrollbars scrollType)
        {
            m_scrollType = scrollType;
        }

        /// <summary>
        /// 缩放
        /// </summary>
        /// <param name="top"></param>
        /// <param name="left"></param>
        /// <param name="height"></param>
        /// <param name="width"></param>
        public void Resize(int top, int left, int height, int width)
        {
            if (top < 0 || left < 0 || height < 0 || width < 0)
                return;

            m_top = top;
            m_left = left;
            m_height = height;
            m_width = width;

            InitBarSize();
        }

        /// <summary>
        /// 显示
        /// </summary>
        /// <param name="graphic"></param>
        public void Paint(Graphics graphic)
        {
            int center;

            switch (m_scrollType)
            {
                case LogicScrollbars.Horizontal:
                    center = m_top + (m_height >> 1) + 2;
                    graphic.DrawLine(m_linePen, m_left, center, m_left + m_width - 1, center);

                    if (m_barStart >= 0)
                    {
                        graphic.FillRectangle(Brushes.Gray, m_barStart, m_top + 4, m_barWidth, m_height - 4);
                    }
                    break;
                case LogicScrollbars.Vertical:
                    center = m_left + (m_width >> 1) + 2;
                    graphic.DrawLine(m_linePen, center, m_top, center, m_top + m_height - 1);

                    if (m_barStart >= 0)
                    {
                        graphic.FillRectangle(Brushes.Gray, m_left + 4, m_barStart, m_width - 4, m_barWidth);
                    }
                    break;
            }
        }

        public void Previous()
        {

        }

        public void Backward()
        {

        }
    }
    #endregion
}
